package com.ruoyi.project.report.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.handler.AbstractRowWriteHandler;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.CommonResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.project.domain.ReportTest;
import com.ruoyi.project.report.server.IReportTestService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 测试Controller
 *
 * @author ruoyi
 * @date 2024-07-04
 */
@Api(tags = "测试")
@RestController
@RequestMapping("/system/test")
public class ReportTestController extends BaseController {
    @Autowired
    private IReportTestService reportTestService;

    /**
     * 导出测试列表
     */
    @PreAuthorize("@ss.hasPermi('system:test:export')")
    @Log(title = "测试", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response) throws IOException {
        List<ReportTest> list = reportTestService.selectReportTestList();
        ExcelUtil<ReportTest> util = new ExcelUtil<ReportTest>(ReportTest.class);
//        util.exportExcel(response, list, "测试数据");
//        util.exportEasyExcel(response, list, "测试数据");

        LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(10, 5);
//        LoopMergeStrategy loopMergeStrategy2 = new LoopMergeStrategy(4, 4);
////        String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
//        ServletOutputStream stream = response.getOutputStream();
//        System.out.println(stream);
//        EasyExcel.write(response.getOutputStream(), ReportTest.class)
//                .registerWriteHandler(loopMergeStrategy2)
//                .registerWriteHandler(loopMergeStrategy)
//                .sheet("测试数据").doWrite(list);
        ServletOutputStream stream = response.getOutputStream();
        System.out.println(stream);

//        String fileName = "自定义文件名.xlsx"; // 包含非 ASCII 字符的文件名
//        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); // 对文件名进行 URL 编码
//        response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\""); // 设置头部，注意引号的使用

//        EasyExcel.write(response.getOutputStream(), ReportTest.class)
//                .registerWriteHandler(new DynamicMergeWriteHandler(list))
//                .sheet("测试数据").doWrite(list);
        EasyExcel.write(response.getOutputStream(), ReportTest.class)
                .registerWriteHandler(new DynamicMergeWriteHandler2(list))
                .sheet("测试数据").doWrite(list);
    }

    // 自定义写处理器，实现单元格合并
    public static class DynamicMergeWriteHandler2 extends AbstractRowWriteHandler {
        private final List<ReportTest> dataList;
        private final Map<String, Integer> mergeMap = new HashMap<>();
        private final Map<String, Integer> bigMergeMap = new HashMap<>();

        public DynamicMergeWriteHandler2(List<ReportTest> dataList) {
            this.dataList = dataList;
            calculateMergeRanges();
        }

        int count = 0;

        @Override
        public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
            if (isHead) {
                return;
            }

//            System.out.println(relativeRowIndex);

//            String mergeValue = dataList.get(relativeRowIndex - 1).getMerge();
            String mergeValue = dataList.get(relativeRowIndex).getMerge();
            if (mergeValue != null && mergeMap.containsKey(mergeValue)) {
                int firstRow = findFirstRowForMerge(mergeValue, dataList, "merge");
                int lastRow = firstRow + mergeMap.get(mergeValue) - 1;
                if (relativeRowIndex == lastRow - 1) {
                    writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(firstRow, lastRow, 4, 4));
                }
            }


            String bigMergeValue = dataList.get(relativeRowIndex).getBigMerge();
            if (bigMergeValue != null && bigMergeMap.containsKey(bigMergeValue)) {
                int firstRow = findFirstRowForMerge(bigMergeValue, dataList, "bigMerge");
                int rowsToMerge = bigMergeMap.get(bigMergeValue);
                int lastRow = firstRow + rowsToMerge - 1;

                if (relativeRowIndex == lastRow - 1) {
//                    writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(firstRow, lastRow, 1, 1));
                    writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(firstRow, lastRow, 5, 5));
                }
            }

//            String bigMergeValue = dataList.get(relativeRowIndex - 1).getBigMerge();
//            String bigMergeValue = dataList.get(relativeRowIndex).getBigMerge();
//            if (bigMergeValue != null && bigMergeMap.containsKey(bigMergeValue)) {
//                int firstRow = findFirstRowForMerge(bigMergeValue, dataList, "bigMerge");
//                int lastRow = firstRow + bigMergeMap.get(bigMergeValue) - 1;
////                if (relativeRowIndex - 1 == lastRow) {
////                    writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(firstRow, lastRow, 1, 1));
////                }
//                if (relativeRowIndex == lastRow) {
//                    writeSheetHolder.getSheet().addMergedRegion(new CellRangeAddress(firstRow, lastRow, 1, 1));
//                }
//            }
        }

        private void calculateMergeRanges() {
            for (int i = 0; i < dataList.size(); i++) {
                ReportTest item = dataList.get(i);
                if (item.getMerge() != null) {
                    mergeMap.put(item.getMerge(), mergeMap.getOrDefault(item.getMerge(), 0) + 1);
                }
                if (item.getBigMerge() != null) {
                    bigMergeMap.put(item.getBigMerge(), bigMergeMap.getOrDefault(item.getBigMerge(), 0) + 1);
                }
            }
        }

        private int findFirstRowForMerge(String value, List<ReportTest> dataList, String property) {
            for (int i = 0; i < dataList.size(); i++) {
                ReportTest item = dataList.get(i);
                if (property.equals("merge") && value.equals(item.getMerge())) {
                    return i + 1; // +1 因为行号从0开始
                } else if (property.equals("bigMerge") && value.equals(item.getBigMerge())) {
                    return i + 1;
                }
            }
            return -1;
        }
    }

    @Anonymous
    @ApiOperation(value = "测试列表", notes = "测试列表")
    @GetMapping("/list")
    public AjaxResult list(ReportTest reportTest) {
        List<ReportTest> list = reportTestService.selectReportTestList();
        return success(list);
    }

    @Anonymous
    @ApiOperation(value = "测试列表2", notes = "测试列表2")
    @GetMapping("/test")
    public CommonResult test(ReportTest reportTest) {
        List<ReportTest> list = reportTestService.selectReportTestList();
        return CommonResult.success(list);
    }

    @Anonymous
    @ApiOperation(value = "测试列表3", notes = "测试列表3")
    @GetMapping("/test3")
    public CommonResult<ReportTest> test3(ReportTest reportTest) {
        List<ReportTest> list = reportTestService.selectReportTestList();
        return CommonResult.success(list);
    }

    @Anonymous
    @ApiOperation(value = "测试列表Map", notes = "测试列表Map")
    @GetMapping("/testMap")
    public CommonResult<Map<String, List<ReportTest>>> testMap(ReportTest reportTest) {
        List<ReportTest> list = reportTestService.selectReportTestList();
        HashMap<String, List<ReportTest>> map = new HashMap<>();
        return CommonResult.success(map);
    }

    @Anonymous
    @ApiOperation(value = "测试json", notes = "测试json")
    @GetMapping("/json")
    public CommonResult<ReportTest> json(@RequestBody ReportTest reportTest) {
        System.out.println(reportTest);
        List<ReportTest> list = reportTestService.selectReportTestList();
        return CommonResult.success(list);
    }
}
